package com.bum.rss.bo;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.core.task.TaskExecutor;

import com.bum.rss.bo.om.CatCacheDTO;
import com.bum.rss.dao.EntryDAO;
import com.bum.rss.exp.om.RssEntry;
import com.bum.rss.site.Site;
import com.bum.rss.site.util.BaseParser;
import com.mg.me.data.grid.IGridMap;

public class SiteLoader {
	Logger			log	= Logger.getLogger(getClass());

	IGridMap		entryGridMap, catGridMap;
	EntryDAO		entryDAO;

	TaskExecutor	executor;

	public List<RssEntry> listSiteCat(Site site, String user) {
		return site.listSiteCats(user);
	}

	public List<RssEntry> listCatEntrys(String url, final Site site, final String cat, final String user) {
		CatCacheDTO catCacheDTO = null;

		final String key = url;
		catCacheDTO = (CatCacheDTO) catGridMap.get(key);
		if (catCacheDTO != null) {
			try {
				return catCacheDTO.getEntries();
			} finally {
				if (System.currentTimeMillis() - catCacheDTO.getCreatedMs() > site.getCatCacheDuration()) {
					// hết hạn, load lại cache
					executor.execute(new Runnable() {
						@Override
						public void run() {
							loadCat(site, cat, user, key);
						}
					});
				}
			}
		}

		return loadCat(site, cat, user, key);
	}

	private List<RssEntry> loadCat(Site site, String cat, String user, String key) {
		List<RssEntry> entrys;
		entrys = site.listCatEntrys(cat, user);
		if (entrys == null) {
			return null;
		}

		for (RssEntry entry : entrys) {
			if (entry.getUrl().startsWith("http")) {
				entry.setUrl(site.getRssLink(entry.getUrl()));
			}
		}

		CatCacheDTO catCacheDTO = new CatCacheDTO();
		catCacheDTO.setCreatedMs(System.currentTimeMillis());
		catCacheDTO.setEntries(entrys);

		if (null != entrys && !Site.MENU_CAT.equals(cat)) {
			entrys.add(0, new RssEntry(site.getHomeCat() == null ? site.getCode() : site.getCode() + "/" + Site.MENU_CAT, Site.MENU_CAT_TITLE));
		}

		catGridMap.put(key, catCacheDTO);
		return entrys;
	}

	public RssEntry loadEntry(String url, Site site, String path, String user) {
		RssEntry entry = null;

		String[] parts = StringUtils.split(url, "/", 3);
		String key = site.getEntryCachePrefix() + parts[0] + "/m/" + parts[2];
		entry = (RssEntry) entryGridMap.get(key);
		if (entry != null) {
			return entry;
		}

		boolean needCacheToDb = false;
		if (site.isEntryDbCache()) {
			// thử đọc từ db trước
			entry = entryDAO.get(site.getCode(), path);
			if (entry == null) {
				needCacheToDb = true;
			}
		}

		if (entry == null) {
			entry = site.loadEntry(path, user);
		}

		if (entry == null || entry.getContent() == null) {
			return null;
		}

		String html = entry.getContent();
		html = MediaHelper.cleanImg(html, site.getImgBase());
		html = normalize(html);
		entry.setContent(html);

		entryGridMap.put(key, entry);
		if (needCacheToDb) {
			entryDAO.add(site.getCode(), path, entry.getTitle(), entry.getContent());
		}

		return entry;
	}

	private static final String[]	REPLACE_FROM	= new String[] {
			"“", "”", " ", " ", "　"
													};
	private static final String[]	REPLACE_TO		= new String[] {
			"\"", "\"", " ", " ", " "
													};
	private static String[]			retainTags		= {
			"p", "br", "div", "h1", "td", "tr"
													};
	private static String			retainRegex		= BaseParser.genRetainTags(retainTags);

	public static String normalize(String html) {
		html = BaseParser.replaceMediaObject(html);
		try {
			html = BaseParser.lowerHtmlTag(html);
		} catch (Exception e) {
		}

		html = clearEmbed(html);

		html = BaseParser.cleanAttribute(html);
		html = BaseParser.retainTags(html, retainRegex);

		if (StringUtils.isBlank(html)) {
			return null;
		}

		html = StringUtils.replaceEach(html, REPLACE_FROM, REPLACE_TO).replaceAll("\\s*<[/]?p>\\s*", "\n").replaceAll("\\s*<br[/]?>\\s*", "\n")
				.replaceAll("\\s*<[/]?div>\\s*", "\n").replaceAll("\\s*<[/]?h1>\\s*", "\n").replaceAll("\\s*<[/]?td>\\s*", " ")
				.replaceAll("\\s*<[/]?tr>\\s*", "\n").replaceAll("\n[\n|\\s| ]*", "\n").replaceAll("[ ]+", " ").trim();

		return html;
	}

	public static String clearEmbed(String html) {
		if (StringUtils.isBlank(html)) {
			return null;
		}

		return html.replaceAll("<script.*?</script>", "").replaceAll("<style.*?</style>", "").replaceAll("<!--.*?-->", "");
	}

	/**
	 * SETTERS
	 */
	public void setEntryGridMap(IGridMap entryGridMap) {
		this.entryGridMap = entryGridMap;
	}

	public void setCatGridMap(IGridMap catGridMap) {
		this.catGridMap = catGridMap;
	}

	public void setExecutor(TaskExecutor executor) {
		this.executor = executor;
	}

	public void setEntryDAO(EntryDAO entryDAO) {
		this.entryDAO = entryDAO;
	}
}
